package com.wzw.springboot.principle.aop;

import com.wzw.springboot.principle.annotation.MvcExt;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;

/**
 * 使用spring代理的aop切面编程
 * @author Wangzhiwen
 */
@Aspect
@Component
public class ServiceAop {

    public ServiceAop() {
        System.out.println("1111111111111");
        System.out.println("1111111111111");
        System.out.println("1111111111111");
        System.out.println("1111111111111");
    }

    //编写通知的方法，前置通知、后置通知、返回通知、异常通知、环绕通知

    /**
     * 增强表达式的抽取
     */
    @Pointcut("execution(public * com.wzw.springboot.principle.aop.Target.*(..))")
    public void pointCut(){}

    @Pointcut("@annotation(com.wzw.springboot.principle.annotation.MvcExt)")
    public void pointCut2(){}

    /**
     * 前置通知 @Before("表达式")
     */
    @Before(value = "pointCut()")
    public void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        String name = joinPoint.getSignature().getName();
        String kind = joinPoint.getKind();
        System.out.println("前置通知 ：方法"+name+"已运行.."+"参数为："+ Arrays.toString(args)+kind);
    }

    /**
     * 后置增强
     */
    @After(value = "pointCut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println("后置增强，方法结束之后运行.....");
    }

    /**
     * 返回通知
     */
    @AfterReturning(value = "pointCut2()",returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result) throws IllegalAccessException {
        System.out.println("返回通知，在目标方法正常返回之后运行..."+"返回值为："+result);
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 方法是否包含注解
        MvcExt annotation = method.getAnnotation(MvcExt.class);
        boolean annotationPresent = method.isAnnotationPresent(MvcExt.class);
        if (!annotationPresent) {
            return;
        }
        Parameter[] parameters = method.getParameters();
        for (Parameter parameter : parameters) {
            boolean present = parameter.isAnnotationPresent(MvcExt.class);

        }
        Object[] args = joinPoint.getArgs();
        Stu stu = new Stu();
        // 获取参数包含特定注解的值
        for (Object arg : args) {
            Field[] declaredFields = arg.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                // 字段是否包含注解
                boolean present = field.isAnnotationPresent(MvcExt.class);
                if (present) {
                    Object o = field.get(stu);

                }
            }
        }

    }

    /**
     * 异常通知
     */
    @AfterThrowing(value = "pointCut()",throwing = "ex")
    public void logException(JoinPoint joinPoint,Exception ex){
        System.out.println("异常通知，目标方法发生异常后运行...."+"异常类型为："+ex.getClass());
    }

    //5.环绕通知
    //@Around(value = "pointCut()")
    //public void logAround(){}

}
